#ifndef CMATRIX_H_
#define CMATRIX_H_

#include "cmatrixbase.h"
#include "cintmath.h"
#include "../exception/cmatrixnotregexception.h"
#include "../exception/cmatrixnotsymmetricexception.h"

/**
 * CMatrix - class representing general (m x n) matrix
 * @author Michal Rost
 * @date 10.01.2007
 */
template <typename T> class CMatrix : public CMatrixBase<T> {
public:
  CMatrix();
  CMatrix(TIndex numOfRows, TIndex numOfCols);
  CMatrix(TIndex numOfRows, TIndex numOfCols, T items[]);
  CMatrix(int type, vector<CVector<T> > v);
  CMatrix(int type, TIndex numOfVectors, CVector<T> v[]);
  CMatrix(const CMatrix<T> &m);
  CMatrix(const CMatrixBase<T> &v);
  CMatrix(const CMatrix<T> &m, const CVector<T> &v, int vType);
  CMatrix(const CMatrix<T> &m1, const CMatrix<T> &m2);
  virtual ~CMatrix();
  CMatrix<T>& operator =(const CMatrix<T> &m);
  CMatrix<T>& operator +=(const CMatrix<T> &m);
  CMatrix<T>& operator -=(const CMatrix<T> &m);
  CMatrix<T>& operator *=(const CMatrix<T> &m);
  CMatrix<T>& operator *=(T num);
  CMatrix<T>& operator /=(T num);
  CMatrix<T> operator +(const CMatrix<T> &m) const;
  CMatrix<T> operator -(const CMatrix<T> &m) const;
  CMatrix<T> operator *(const CMatrix<T> &m) const;
  CMatrix<T> operator *(T num) const;
  CMatrix<T> operator /(T num) const;
  CMatrix<T> getBase();
  CMatrix<T> subMatrix(TIndex sr, TIndex sc, TIndex er, TIndex ec);
  T getDet();
  void invert();
  void findEigenValuesAndVectorsWithLU(CMatrix<T> &eigenVals,
      CMatrix<T> &eigenVecs);
  void pow(unsigned int exp);
  bool isRegular() const;
  TIndex getRank() const;
  TIndex getNumOfRows() const;
  TIndex getNumOfCols() const;
  static CVector<T> mul(const CMatrix<T> &m, const CVector<T> &v);
  static CVector<T> mul(const CVector<T> &v, const CMatrix<T> &m);
  static string getClassName() {
    return "CMatrix";
  }
protected:
  TIndex numOfRows;
  TIndex numOfCols;
  void setNumOfRows(TIndex numOfRows);
  void setNumOfCols(TIndex numOfCols);
};

#endif
